package cmd

import (
	"compress/gzip"
	"io"
	"net/url"
	"os"
	"strconv"
	"strings"

	"gitee.com/bjf-fhe/apicat/openapi"
	"github.com/getkin/kin-openapi/openapi3"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

type Config struct {
	Definition      string
	UserName        string
	Config          string
	Format          string
	Server          string
	ServerVariables []string
	SourceMode      string
	StaticFileTypes []string
	Debug           int
	TimeFormat      string
	file            string
}

var rootConfig Config

func (c *Config) GetTimeFormat() string {
	return c.TimeFormat
}

func (c *Config) GetFileName() string {
	return c.file
}

func (c *Config) IsLocalFile() bool {
	_, err := os.Stat(c.file)
	if err == nil {
		return true
	}
	if !os.IsNotExist(err) {
		logrus.Error("check file exists error:", err)
	}
	return false
}

func (c *Config) Check() error {
	if c.Format == "" {
		if c.Config == "" {
			c.Format = "main"
		} else {
			return errors.New("日志格式不能为空")
		}
	}
	logrus.SetLevel(logrus.Level(c.Debug))
	return nil
}

func (c *Config) IsStaticPath(path string) bool {
	for _, v := range c.StaticFileTypes {
		if strings.HasSuffix(path, v) {
			return true
		}
	}
	return false
}

func (c *Config) LoadApi() (api *openapi3.T, baseUrl string, err error) {
	err = c.Check()
	if err == nil {
		api, err = openapi.Load(c.Definition, c.UserName)
		if err == nil {
			var iS int
			iS, err = strconv.Atoi(c.Server)

			baseUrl = "/"

			if err == nil {
				if len(api.Servers) == 0 {
					logrus.Errorln("OpenAPI定义文档并未提供服务器信息，使用默认前缀'/'")
				} else if len(api.Servers) > iS+1 {
					logrus.Errorf("提供的服务器信息编号%d不存在，提供的服务器信息包括：", iS)
					for k, v := range api.Servers {
						logrus.Errorf("[%d](%s)%s", k, v.Description, v.URL)
					}
				} else {
					var inputedVariables = make(map[string]string)
					for _, arg := range c.ServerVariables {
						parts := strings.SplitN(arg, ":", 2)
						if len(parts) == 2 {
							inputedVariables[parts[0]] = parts[1]
						}
					}
					var server = api.Servers[iS]

					for k, _ := range server.Variables {
						if inputed, ok := inputedVariables[k]; ok {
							server.Variables[k].Default = inputed
						}
					}
					baseUrl, err = server.BasePath()
					if err != nil {
						err = errors.Wrap(err, "获取服务器地址出错")
						return
					}
				}
			}

			var u *url.URL

			u, err = url.Parse(baseUrl)

			if err != nil {
				err = errors.Wrap(err, "分析服务器地址出错")
				return
			}

			baseUrl = u.Path //因为nginx日志没有域名信息，只需要path部分

			if baseUrl != "/" {
				logrus.Infoln("判定的根路径为：", baseUrl)
			} else {
				baseUrl = ""
			}

			logrus.Info("开始进行日志读取分析")
		}
	}
	return
}

type ZipReadCloser struct {
	Zip io.ReadCloser
	Low io.ReadCloser
}

func (z *ZipReadCloser) Close() error {
	err := z.Zip.Close()
	if err == nil {
		return z.Low.Close()
	}
	return err
}

func (z *ZipReadCloser) Read(p []byte) (n int, err error) {
	return z.Zip.Read(p)
}

func (c *Config) OpenFile() (io.ReadCloser, error) {

	file, err := os.Open(c.file)
	if err != nil {
		return nil, err
	}

	if strings.HasSuffix(c.file, ".gz") {
		fz, err := gzip.NewReader(file)
		if err != nil {
			return nil, err
		}
		return &ZipReadCloser{
			Zip: fz,
			Low: file,
		}, nil
	} else {
		return file, nil
	}
}
